// 云函数入口文件
const cloud = require("wx-server-sdk");
const nodeExcel = require("excel-export");
const path = require("path");
const moment = require("moment");
const MAX_LIMIT = 100;

cloud.init();

// 云函数入口函数
exports.main = async (event, context) => {
  let { isManual } = { event };
  if (!isManual) {
    isManual = false;
  }
  var tableHead = [
    "名次",
    "编号",
    "分组",
    "姓名",
    "跑步卡",
    "力量卡",
    "越野卡",
    "跳绳",
    "爬楼",
    "周训",
    "活动卡",
    "本月积分",
    "总积分",
    "当月跑量",
    "爬升距离",
    "爬楼层数",
    "力量时间",
    "跳绳个数",
    "参加活动数",
  ];
  var tableMap = {
    styleXmlFile: path.join(__dirname, "styles.xml"),
    name: Date.now() + "-export",
    cols: [],
    rows: [],
  };
  //添加表头  此处要注意格式type，会影响到rows
  tableMap.cols = [
    {
      caption: tableHead[0],
      type: "number",
    },
    {
      caption: tableHead[1],
      type: "string",
    },
    {
      caption: tableHead[2],
      type: "string",
    },
    {
      caption: tableHead[3],
      type: "string",
    },
    {
      caption: tableHead[4],
      type: "number",
    },
    {
      caption: tableHead[5],
      type: "number",
    },
    {
      caption: tableHead[6],
      type: "number",
    },
    {
      caption: tableHead[7],
      type: "number",
    },
    {
      caption: tableHead[8],
      type: "number",
    },
    {
      caption: tableHead[9],
      type: "number",
    },
    {
      caption: tableHead[10],
      type: "number",
    },
    {
      caption: tableHead[11],
      type: "number",
    },
    {
      caption: tableHead[12],
      type: "number",
    },
    {
      caption: tableHead[13],
      type: "number",
    },
    {
      caption: tableHead[14],
      type: "number",
    },
    {
      caption: tableHead[15],
      type: "number",
    },
    {
      caption: tableHead[16],
      type: "number",
    },
    {
      caption: tableHead[17],
      type: "number",
    },
    {
      caption: tableHead[18],
      type: "number",
    },
  ];

  //单列数据
  const Output = [];
  const db = cloud.database();
  const _ = db.command;

  const activityTotalCount = await db
    .collection("activity")
    .where({
      isActivity: true,
    })
    .count();
  var team = "scu14";
  const userCount = await db
    .collection("user")
    .where({
      isMember: true,
      team: team,
    })
    .count();
  const userTotal = userCount.total;
  // 计算需分几次取
  const userBatchTimes = Math.ceil(userTotal / 100);
  const userTasks = [];

for (let i = 0; i < userBatchTimes; i++) {
  const promise = db
    .collection("user")
    .where({
      isMember: true,
      team: team,
    })
    .orderBy("point", "desc")
    .skip(i * MAX_LIMIT)
    .limit(MAX_LIMIT)
    .get()
    .catch(error => {
      console.error(`Error fetching users: ${error}`);
      throw error;
    });
  userTasks.push(promise);
}

const userData = (await Promise.all(userTasks)).reduce((acc, cur) => {
  return {
    data: acc.data.concat(cur.data),
    errMsg: acc.errMsg,
  };
}, { data: [], errMsg: '' });
const userList = userData.data;

moment.locale("zh-cn");
const month = moment().utcOffset(480);
month.subtract(1, "months");
month.set({ hour: 0, minute: 0, second: 0, millisecond: 0 });
const startMonthDate = month.startOf("month").valueOf();
console.log(month.startOf("month").format("lll"));

const endMonth = moment().utcOffset(480);
endMonth.subtract(1, "months");
const endMonthDate = endMonth.endOf("month").valueOf();
console.log(endMonth.endOf("month").format("lll"));

for (let i = 0; i < userList.length; i++) {
  const user = userList[i];
  try {
    const userActivityCnt = await db
      .collection("registration-form")
      .where({
        _openid: user._openid,
      })
      .count();

    const monthCount = await db
      .collection("cards")
      .where({
        _openid: user._openid,
        systemTime: _.lte(endMonthDate).and(_.gte(startMonthDate)),
      })
      .count();

    let monthPoints = Array(8).fill(0)
    let totleMonthPoint = 0;
    let monthDistance = 0;
    let monthHeight = 0;
    let monthFloor = 0;
    let monthTime = 0;
    let monthRopeNo = 0;

    if (monthCount.total > 0) {
      const monthBatchTimes = Math.ceil(monthCount.total / MAX_LIMIT);
      const monthTasks = [];
      for (let j = 0; j < monthBatchTimes; j++) {
        const promise = db
          .collection("cards")
          .where({
            _openid: user._openid,
            systemTime: _.lte(endMonthDate).and(_.gte(startMonthDate)),
          })
          .skip(j * MAX_LIMIT)
          .limit(MAX_LIMIT)
          .get()
          .catch(error => {
            console.error(`Error fetching cards: ${error}`);
            throw error;
          });
        monthTasks.push(promise);
      }

      const monthCards = (await Promise.all(monthTasks)).reduce((acc, cur) => {
        return {
          data: acc.data.concat(cur.data),
          errMsg: acc.errMsg,
        };
      }, { data: [], errMsg: '' });
      const monthCardList = monthCards.data;

      for (let k = 0; k < monthCardList.length; k++) {
        const card = monthCardList[k];
        if (card.status === "checked") {
          monthPoints[card.type.index] += card.point;
          if (card.type.index === 0 || card.type.index === 2) {
            monthDistance += parseFloat(card.distance);
          }
          if (card.type.index === 1) {
            monthTime += parseFloat(card.time);
          }
          if (card.type.index === 2) {
            monthHeight += parseFloat(card.altitude);
          }
          if (card.type.index === 4) {
            monthFloor += parseFloat(card.level);
          }
          if (card.type.index === 3) {
            monthRopeNo += parseFloat(card.ropeNo);
          }
        }
      }

      totleMonthPoint = monthPoints.reduce((sum, point) => sum + point, 0);
      console.log("user", user.nickName);
      console.log("totleMonthPoint", totleMonthPoint);
    }

    const userInfoData = await db
      .collection("userInfo")
      .where({
        _openid: user._openid,
      })
      .get();

    let totlePoint = 0;
    if (userInfoData.data.length !== 0) {
      totlePoint = userInfoData.data[0].point;
    }
    if (!user.groupName) {
      user.groupName = "还未选组";
    }

    Output.push({
      名次: i + 1,
      编号: user.index,
      分组: user.groupName,
      姓名: user.nickName,
      跑步卡: monthPoints[0],
      力量卡: monthPoints[1],
      越野卡: monthPoints[2],
      跳绳卡: monthPoints[3],
      爬楼卡: monthPoints[4],
      周训: monthPoints[5],
      活动卡: monthPoints[6],
      瑜伽卡: monthPoints[7],
      本月积分: totleMonthPoint,
      总积分: totlePoint,
      当月跑量: monthDistance,
      爬升距离: monthHeight,
      爬楼层数: monthFloor,
      力量时间: monthTime,
      跳绳个数: monthRopeNo,
      参加活动数: userActivityCnt.total,
    });
  } catch (error) {
    console.error(`Error processing user ${i}: ${error}`);
  }
}

// 添加每一行数据
for (let i = 0; i < Output.length; i++) {
  tableMap.rows[tableMap.rows.length] = [
    Output[i].名次,
    Output[i].编号,
    Output[i].分组,
    Output[i].姓名,
    Output[i].跑步卡,
    Output[i].力量卡,
    Output[i].越野卡,
    Output[i].跳绳卡,
    Output[i].爬楼卡,
    Output[i].周训,
    Output[i].活动卡,
    Output[i].本月积分,
    Output[i].总积分,
    Output[i].当月跑量,
    Output[i].爬升距离,
    Output[i].爬楼层数,
    Output[i].力量时间,
    Output[i].跳绳个数,
    Output[i].参加活动数,
  ];
}

// 保存excelResult到相应位置
const excelResult = nodeExcel.execute(tableMap);
const filePath = "outputExcels";
const date = moment().add(8, "hours").format("YYYY_MM_DD_hh_mm");
const fileName = `${date}川行者月积分.xlsx`;
return await cloud.uploadFile({
  cloudPath: path.join(filePath, fileName),
  fileContent: new Buffer(excelResult, "binary"),
});
};
